package com.jwm.client.soft;

import cn.hutool.json.JSONUtil;
import com.jwm.model.FilesVo;
import org.apache.commons.io.input.ReversedLinesFileReader;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 崔洁
 */
@Component
public class FileTool {
    private static final Logger logger = LoggerFactory.getLogger(FileTool.class);

    public static void main(String[] args) throws Exception {

        String line = "2024/07/29  15:37             4,829    proxm    oxve. sh    ";
        System.out.println(line);
        System.out.println(line.substring(0, 17));
        System.out.println(line.substring(17, 36).trim());
        System.out.println(line.substring(36).trim());

        // List<FilesVo> files = new FileTool().getFiles("D:/server/apache-tomcat-7.0.108/logs");
        // System.out.println(files.size());
        // String p = new FileTool().yasuoFile("D:/server/apache-tomcat-7.0.108/logs/1.mp4");
        // System.out.println(p);
        // ArrayDeque<String> deque = new FileTool().lastLine("logs/info.2025-09-20.log", 10);
        // while (deque.size() > 0) {
        //     System.out.println(deque.getFirst());
        //     deque.pollFirst();
        // }
    }

    //读取文件夹下内容
    public List<FilesVo> getFiles(String path) {
        if (StringUtils.isBlank(path)) {
            return null;
        }
        List<FilesVo> file = getFile("cmd", "/c", "cd", "/d", path, "&&", "dir");
        logger.info("客户端 -> 获取文件列表\n{}", JSONUtil.toJsonStr(file));
        return file;
    }

    public List<FilesVo> getFile(String... cmd) {
        List<FilesVo> filesVoList = new ArrayList<>();
        try {
            // 创建一个ProcessBuilder实例，指定命令和参数
            ProcessBuilder builder = new ProcessBuilder(cmd);
            // 将错误输出和标准输出合并，便于读取
            builder.redirectErrorStream(true);
            // 启动进程
            Process process = builder.start();
            // 设置字符编码为GBK
            builder.environment().put("CMD_ENCODING", "GBK");
            // 获取命令结果的输入流并读取输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            boolean begin = false;
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.length() > 36 && line.substring(36).trim().equals("..")) {
                    begin = true;
                    continue;
                }
                if (!begin || line.equals("")) {
                    continue;
                }

                String date = line.substring(0, 17);
                String size = line.substring(17, 36).trim();
                String name = line.substring(36).trim();

                if (line.substring(0, 10).trim().equals("")) {
                    continue;
                }
                FilesVo filesVo = new FilesVo();
                filesVo.setName(name);
                filesVo.setPath(cmd[4] + "/" + name);
                filesVo.setLastModifiedDate(date);
                if (!size.equals("<DIR>")) {
                    filesVo.setSize(formatSize(size));
                    filesVo.setType("文件");
                } else {
                    filesVo.setType("路径");
                    String[] childCmd = new String[cmd.length];
                    System.arraycopy(cmd, 0, childCmd, 0, cmd.length);
                    childCmd[4] = cmd[4] + "/" + filesVo.getName();
                    filesVo.setChildren(getFile(childCmd));
                }
                filesVoList.add(filesVo);
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("获取文件失败\n{}", e);
        }
        return filesVoList;
    }

    public String yasuoFile(String path) {
        try {
            // 创建一个ProcessBuilder实例，指定命令和参数
            ProcessBuilder builder = new ProcessBuilder("makecab", path, path + ".zip");
            builder.redirectErrorStream(true); // 将错误输出和标准输出合并，便于读取
            // 设置字符编码为GBK
            builder.environment().put("CMD_ENCODING", "GBK");
            // 启动进程
            Process process = builder.start();
            // 获取命令结果的输入流并读取输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.equals("100.00% [flushing current folder]")) {
                    path += ".zip";
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("压缩文件失败\n{}", e);
        }
        return path;
    }

    //读取文件内容
    public ArrayDeque<String> lastLine(String path, int numLastLineToRead) {
        logger.info("客户端 -> 获取文件{}最后{}行开始", path, numLastLineToRead);
        File file = new File(path);
        Charset charset = StandardCharsets.UTF_8;
        ArrayDeque<String> result = new ArrayDeque<>();
        try (ReversedLinesFileReader reader = new ReversedLinesFileReader(file, charset)) {
            String line = "";
            while ((line = reader.readLine()) != null && result.size() < numLastLineToRead) {
                result.addFirst(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("客户端 -> 读取文件{}最后{}行错误\n{}", path, numLastLineToRead, e.getMessage());
        } finally {
            // 注意：在finally块中关闭文件流是一个好习惯，尽管使用try-with-resources会自动处理这一部分。
        }
        logger.info("客户端 -> 获取文件{}最后{}行成功：\n{}", path, numLastLineToRead, JSONUtil.toJsonStr(result));
        return result;
    }

    private String formatSize(String size) {
        long sizeLong = Long.parseLong(size.replaceAll(",", ""));
        if (sizeLong < 1024.0) {
            return size + "B";
        } else if (sizeLong < 1024.0 * 1024.0) {
            return String.format("%.2f", sizeLong / 1024.0) + "KB";
        } else if (sizeLong < 1024.0 * 1024.0 * 1024.0) {
            return String.format("%.2f", sizeLong / 1024.0 / 1024.0) + "MB";
        } else {
            return String.format("%.2f", sizeLong / 1024.0 / 1024.0 / 1024.0) + "GB";
        }
    }
}
